package com.neusoft.databus.agent.interactive.collect;

import java.io.IOException;

import com.neusoft.databus.common.bean.CommandBean;
import com.neusoft.databus.common.exception.ConfigErrorException;
import com.neusoft.databus.common.interactive.collect.Collector;
import com.neusoft.databus.common.parser.Parser;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * basic collector
 *
 * @author naxiang
 * @param <T>
 */
@Slf4j
@Setter
@Getter
public abstract class BasicCollector<T> extends Collector<T> {

    public BasicCollector(final Parser parser) {
        super(parser);
    }

    /**
     * NoSuchElementException: maybe throw by the pool when borrow object.<br>
     * IOException: maybe throw when socket communication. must invalidate
     * pooled object.<br>
     * Don't catch other exception, all will throw to higher layer.
     */
    @Override
    protected void doCollect(final CommandBean command) throws Exception {
        try {
            final long startTime = System.currentTimeMillis();
            if (BasicCollector.log.isDebugEnabled()) {
                BasicCollector.log.debug("borrow connection object from pool {} by {}", command.getConnType(),
                        command.getConnectionStr());
            }
            this.conn = this.connector.getConn(command.getConnection().asUsedConnection());
            if (BasicCollector.log.isDebugEnabled()) {
                BasicCollector.log.debug("success to borrow connection object from pool {}，elapsed {} ms.",
                        command.getConnType(), System.currentTimeMillis() - startTime);
            }
            this.sendCommand(command);

        } catch (final Exception e) {
            throw e;
        } finally {
            try {
                if (BasicCollector.log.isDebugEnabled()) {
                    BasicCollector.log.debug("return connection object to poll, {}", command.getConnection());
                }
                this.connector.returnConn(command.getConnection().asUsedConnection(), this.conn);
            } catch (final Exception e) {

            }
        }

        try {
            this.parser.parseCollectResponse(command);
        } catch (final Exception e) {
            throw new ConfigErrorException("解析指标值时出错", e);
        }
        if (BasicCollector.log.isDebugEnabled()) {
            command.getResourceBean().forEach(r -> {
                r.getMetrics().stream().filter(it -> it.isExecutedSuccess()).forEach(data -> {
                    BasicCollector.log.debug("{}", data);
                });
            });

        }

    }

    /**
     * @param command
     * @return
     * @throws InterruptedException
     * @throws IOException 当连接出现问题时抛出
     */
    public abstract void sendCommand(CommandBean command) throws InterruptedException, IOException;
}
